package reflection;

import java.lang.reflect.*;

/**
 * @author liweimin
 * @date 2021/4/14 17:19
 * @description
 * @since
 */
public class DynamicProxyInstance {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        InvocationHandler handler = new MyInvocationHandler(new CalculatorImpl1());

        //获取“代理类”对象 $Proxy0,
        Class proxyClass = Proxy.getProxyClass(Calculator1.class.getClassLoader(), Calculator1.class);

        //获取构造器  protected Proxy(InvocationHandler h) {
        //        Objects.requireNonNull(h);
        //        this.h = h;
        //    }
        Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);

        //构造代理对象---->本质上将接口实例化成一个代理对象（该对象继承Proxy类，调用接口的相应方法，会调用invoke方法）
        Calculator1 calculator1 = (Calculator1) constructor.newInstance(handler);


        Class calculator1Class = calculator1.getClass();
        System.out.println("代理实例的类型： " + calculator1Class.getName());
        System.out.println("代理实例的父类： " + calculator1Class.getSuperclass());

        for (Method method : calculator1Class.getDeclaredMethods()) {
            System.out.println("代理实例的接口：" + method);
        }

        calculator1.add(12, 43);

        System.out.println("================================================我是分割线===============================================");
        Object obj =  constructor.newInstance(handler);
        Method method = obj.getClass().getDeclaredMethod("add", int.class, int.class);
        method.invoke(obj,12,34);

//        proxyClass.
    }
}

interface Calculator1 {
    int add(int a, int b);
}

class CalculatorImpl1 implements Calculator1 {

    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

class MyInvocationHandler implements InvocationHandler {

    private Object object;

    public MyInvocationHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-----------------------12345-----------------------");
        Object invoke = method.invoke(object, args);
        System.out.println("-----------------------54321-----------------------");
        return invoke;
    }
}
